#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>

#include "protocol.h"

int main(int argc, char *argv[])
{
    int sockfd;
    struct sockaddr_in localAddr, remoteAddr;
    socklen_t remoteAddrLen = sizeof(struct sockaddr_in);
    char buf[BUFSIZ] = "";

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket()");
        exit(1);
    }

    int optval = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

    localAddr.sin_family = AF_INET;
    localAddr.sin_port = ntohs(PORT);
    inet_aton("0.0.0.0", &localAddr.sin_addr);
    if (bind(sockfd, (struct sockaddr*) &localAddr, sizeof(localAddr)))
    {
        perror("bind");
        goto CleanUp;
    }

    if (listen(sockfd, 10))
    {
        perror("listen");
        goto CleanUp;
    }

    printf("Server is running....\n");
    while (1)
    {
        int fd = accept(sockfd, (struct sockaddr*) &remoteAddr, &remoteAddrLen);
        if (fd < 0)
        {
            perror("accept");
            continue;
        }
        printf("Accept from remote %s:%d\n", \
            inet_ntoa(remoteAddr.sin_addr), \
            ntohs(remoteAddr.sin_port));

        if (recv(fd, buf, BUFSIZ, 0) < 0)
        {
            perror("recv");
            goto CloseClient;
        }
        printf("From Client: %s\n", buf);

        const char *msg = "My name is server!";
        if (send(fd, msg, strlen(msg), 0) < 0)
        {
            perror("send");
            goto CloseClient;
        }

      CloseClient:
        close(fd);
    }

  CleanUp:
    close(sockfd);
    return 0;
}

